#include "StdAfx.h"
#include "grammarNormalizer.h"

bool grammarNormalizer::checkValidGrammar(String^ html){
	return checkSpecialTags(html) && checkInputParameterTags(html);
}

/*
	Validates that there is one and exactly one valid attribute id and valid_value
	If there is one valid and one invalid it WILL approve the tag
*/
String^ grammarNormalizer::insertJavaScriptValidation(String^ html){
	String^ regExpInput = "(<input)(.*?)/>";
	String^ htmlWithValidation = "";

	Regex^ rxInput = gcnew Regex(regExpInput, static_cast<RegexOptions>(RegexOptions::IgnoreCase));
	MatchCollection^ matchesInput = rxInput->Matches(html);
	
	int lastPointer = 0;
	for each (Match^ match in matchesInput){
		int index = match->Index;
		int length = match->Length;
		String^ htmlTag = html->Substring(index,length);
		
		//Console::WriteLine(" TAG to change {0}", htmlTag);
		htmlTag = Regex::Replace(htmlTag, "valid_value=\"email\"", "valid_value=\"email\" onchange=\"checkIsEmail(this)\"");
		htmlTag = Regex::Replace(htmlTag, "valid_value=\"alphanumeric\"", "valid_value=\"alphanumeric\" onchange=\"checkIsAlphanumeric(this)\"");
		htmlTag = Regex::Replace(htmlTag, "valid_value=\"numeric\"", "valid_value=\"numeric\" onchange=\"checkIsNumeric(this)\"");
		htmlTag = Regex::Replace(htmlTag, "valid_value=\"alphabetic\"", "valid_value=\"alphabetic\" onchange=\"checkIsAlphabetic(this)\"");
		htmlTag = Regex::Replace(htmlTag, "valid_value=\"all\"", "valid_value=\"all\" onchange=\"checkMatchRegularExpression('.*')\"");
		
		// To change Regular Expression
		String^ regExpValidValueRegExp = "valid_value=\"\\$(?<value>(.*?))\\$\"";
		Regex^ rxExpValidValueRegExp = gcnew Regex(regExpValidValueRegExp, static_cast<RegexOptions>(RegexOptions::IgnoreCase));
		
		if ((rxExpValidValueRegExp->Matches(htmlTag))->Count == 1){
			String^ valueOfRegularExpression = ((rxExpValidValueRegExp->Match(htmlTag))->Result("${value}"));
			//Console::WriteLine("       //Regular Expresion Found  {0}",valueOfRegularExpression);

			htmlTag = Regex::Replace(htmlTag, "valid_value=\"\\$(.*?)\\$\"", "valid_value=\""+valueOfRegularExpression+"\" onchange=\"checkMatchRegularExpression('"+valueOfRegularExpression+"')\"");
		}

		htmlWithValidation = htmlWithValidation + (html->Substring(lastPointer,index));
		htmlWithValidation = htmlWithValidation + htmlTag;
		lastPointer = index+length;
	}

	htmlWithValidation = htmlWithValidation + (html->Substring(lastPointer,html->Length - lastPointer));
	return htmlWithValidation;
}


String^ grammarNormalizer::embedJavaScriptValidationIntoHTML(String^ html){
	// Validating Form Tag
	String^ regExpForm = "(<title>)(.*?)(</title>)";
	Regex^ rxForm = gcnew Regex(regExpForm, static_cast<RegexOptions>(RegexOptions::IgnoreCase));
	MatchCollection^ matchesForm = rxForm->Matches(html);
	
	if (matchesForm->Count != 1){ // Occurs more than once or zero times
		surveyAlligatorException^ ex = gcnew surveyAlligatorException("The Title Tag is not valid according to the grammar specification. Please check that there is one Title Tag '<title> ... </title>'");
		throw (ex);
	}

	Match^ matchForm = matchesForm[0];
	int indexForm = matchForm->Index;

	String^ temp = "";
	String^ content = "";
	System::IO::StreamReader^ sr;
	try{
	  Assembly^ assembly = Assembly::GetExecutingAssembly();
	  StreamReader^ sr = gcnew StreamReader(assembly->GetManifestResourceStream("inputDataValidator.js"));
	  while ( temp = sr->ReadLine() ){
		 content = content + temp;
	  }
	} catch (Exception ^ e){
	  surveyAlligatorException^ ex = gcnew surveyAlligatorException("There was a problem reading the 'inputDataValidator.js' file. This is probably a compilation problem.");
	  throw (ex);

	}finally{ // Close the StreamReader
	   if ( sr ){
		   delete (IDisposable^)sr;
	   }
	}

	html = html->Substring(0,indexForm)+"<script>"+content+"</script>"+html->Substring(indexForm);
	return html;
}
/**

*/
bool grammarNormalizer::validateUniquenessTag(String^ htmlTag){
	String^ regExpActive = "active=\"(?<value>(yes|no))\"";
	Regex^ rxActive = gcnew Regex(regExpActive, static_cast<RegexOptions>(RegexOptions::IgnoreCase));

	if ((rxActive->Matches(htmlTag))->Count == 1){
		String^ valueOfAttrActive = ((rxActive->Match(htmlTag))->Result("${value}"))->ToLower();	
		if (valueOfAttrActive->Equals("yes")){// Its active="yes"
			
			String^ regExpKey_id = "key_id=\"(.+?)\"";
			Regex^ rxKey_id = gcnew Regex(regExpKey_id, static_cast<RegexOptions>(RegexOptions::IgnoreCase));
			String^ regExpRep_plcy = "rep_plcy=\"(append|replacement)\"";
			Regex^ rxRep_plcy = gcnew Regex(regExpRep_plcy, static_cast<RegexOptions>(RegexOptions::IgnoreCase));

			if ((rxKey_id->Matches(htmlTag))->Count == 1 && (rxRep_plcy->Matches(htmlTag))->Count == 1){
				return true;
			}else{
				surveyAlligatorException^ ex = gcnew surveyAlligatorException("The Uniqueness Tag "+htmlTag+" is not valid according to the grammar specification. \n <uniqueness active=\"[yes|no]\" key_id=\"[fieldID]\" rep_plcy=\"[append|replacement]\" />");
				throw (ex);
			}
		
		}else { // Its active="no"
			return true;
		}
	}else{
		surveyAlligatorException^ ex = gcnew surveyAlligatorException("The Uniqueness Tag '"+htmlTag+"' is not valid according to the grammar specification. \n <uniqueness active=\"[yes|no]\" key_id=\"[fieldID]\" rep_plcy=\"[append|replacement]\" />");
		throw (ex);
	}
	surveyAlligatorException^ ex = gcnew surveyAlligatorException("The Uniqueness Tag '"+htmlTag+"' is not valid according to the grammar specification. \n <uniqueness active=\"[yes|no]\" key_id=\"[fieldID]\" rep_plcy=\"[append|replacement]\" />");
	throw (ex);
}
/**
	Is not checking the non precense of strange attributes
*/
bool grammarNormalizer::validateFile_InfoTag(String^ htmlTag){
	//Console::WriteLine("{0}",htmlTag);

	String^ regExpLocation = "location=\"(.+?)\"";
	Regex^ rxLocation = gcnew Regex(regExpLocation, static_cast<RegexOptions>(RegexOptions::IgnoreCase));

	if ((rxLocation->Matches(htmlTag))->Count == 1){
		return true;
	}else{
		surveyAlligatorException^ ex = gcnew surveyAlligatorException("The File_Info Tag '"+htmlTag+"' is not valid according to the grammar specification. \n E.x. <file_info location=\"file.csv\"/>");
		throw (ex);
	}
}
/*
	Validates that there is one and exactly one valid attribute id and valid_value
	If there is one valid and one invalid it WILL approve the tag
*/
bool grammarNormalizer::validateInputTag(String^ htmlTag){
	//Console::WriteLine("{0}",htmlTag);

	String^ regExpId = "id=\".+\"";
	String^ regExpText = "type=\"text\"";
	String^ regExpValidValue = "valid_value=\"(email|alphanumeric|alphabetic|numeric|\\$(.+?)\\$|all)\"";
	
	if ((Regex::Matches(htmlTag, regExpId))->Count == 1 && 
		(	(((Regex::Matches(htmlTag, regExpText))->Count == 1) & (Regex::Matches(htmlTag, regExpValidValue))->Count == 1)
		  || 
			!((Regex::Matches(htmlTag, regExpText))->Count == 1))){
		return true;
	}else{
		surveyAlligatorException^ ex = gcnew surveyAlligatorException("The Input Tag '"+htmlTag+"' is not valid according to the grammar specification. \n E.x. <input id=\"[text]\" [type=\"[text]\" valid_value=\"[email|alphanumeric|alphabetic|numeric|$regular expression$|all]\"] | [type=\"[checkbox|radio]\"] />");
		throw (ex);
	}
}
/*
	Validates that there is one and exactly one valid attribute id and valid_value
	If there is one valid and one invalid it WILL approve the tag
*/
bool grammarNormalizer::validateTextAreaTag(String^ htmlTag){
	//Console::WriteLine("{0}",htmlTag);

	String^ regExpId = "id=\".+\"";
	
	if ((Regex::Matches(htmlTag, regExpId))->Count == 1){
		return true;
	}else{
		surveyAlligatorException^ ex = gcnew surveyAlligatorException("The Text Area Tag '"+htmlTag+"' is not valid according to the grammar specification. <textarea id=\"[text]\"></textarea>");
		throw (ex);
	}
}
/*
	Validates that there is one and exactly one valid attribute id and valid_value
	If there is one valid and one invalid it WILL approve the tag
*/
bool grammarNormalizer::validateSelectTag(String^ htmlTag){
	//Console::WriteLine("{0}",htmlTag);

	String^ regExpId = "id=\".+\"";
	
	if ((Regex::Matches(htmlTag, regExpId))->Count == 1 ){
		return true;
	}else{
		surveyAlligatorException^ ex = gcnew surveyAlligatorException("The Select Tag '"+htmlTag+"' is not valid according to the grammar specification.<select id=\"[text]\"></select>");
		throw (ex);
	}
}

bool grammarNormalizer::checkSpecialTags(String^ html){
	// Validating Special Tag Uniqueness
	String^ regExpUniqueness = "(<uniqueness)(.*?)/>";
	Regex^ rxUniqueness = gcnew Regex(regExpUniqueness, static_cast<RegexOptions>(RegexOptions::IgnoreCase));
	MatchCollection^ matchesUniqueness = rxUniqueness->Matches(html);
	
	if (matchesUniqueness->Count != 1){ // Occurs more than once or zero times
		surveyAlligatorException^ ex = gcnew surveyAlligatorException("The Uniqueness Tag is not valid according to the grammar specification. Please check that there is only ONE Uniqueness Tag");
		throw (ex);
	}

	Match^ matchUniqueness = matchesUniqueness[0];
	int indexUniqueness = matchUniqueness->Index;
	int lengthUniqueness = matchUniqueness->Length;

	if (!validateUniquenessTag(html->Substring(indexUniqueness,lengthUniqueness))){
		return false;
	}
	
	// Validating Special Tag file_info
	String^ regExpFile_info = "(<file_info)(.*?)/>";
	Regex^ rxFile_info = gcnew Regex(regExpFile_info, static_cast<RegexOptions>(RegexOptions::IgnoreCase));
	MatchCollection^ matchesFile_info = rxFile_info->Matches(html);
	
	if (matchesFile_info->Count != 1){ // Occurs more than once or zero times
		surveyAlligatorException^ ex = gcnew surveyAlligatorException("The File_Info Tag is not valid according to the grammar specification. Please check that there is only ONE File_Info Tag.");
		throw (ex);
	}

	Match^ matchFile_info = matchesFile_info[0];
	int indexFile_info = matchFile_info->Index;
	int lengthFile_info = matchFile_info->Length;

	if (!validateFile_InfoTag(html->Substring(indexFile_info,lengthFile_info))){
		return false;
	}
	
	// Validating Title Tag
	String^ regExpTitle = "(<title>)(.*?)(</title>)";
	Regex^ rxTitle = gcnew Regex(regExpTitle, static_cast<RegexOptions>(RegexOptions::IgnoreCase));
	MatchCollection^ matchesTitle = rxTitle->Matches(html);
	
	if (matchesTitle->Count != 1){ // Occurs more than once or zero times
		surveyAlligatorException^ ex = gcnew surveyAlligatorException("The Title Tag is not valid according to the grammar specification. Please check that there is ONE Title Tag");
		throw (ex);
	}

	// Validating Form Tag
	String^ regExpForm = "(<form>)(.*?)(</form>)";
	Regex^ rxForm = gcnew Regex(regExpForm, static_cast<RegexOptions>(RegexOptions::IgnoreCase));
	MatchCollection^ matchesForm = rxForm->Matches(html);
	
	if (matchesForm->Count != 1){ // Occurs more than once or zero times
		surveyAlligatorException^ ex = gcnew surveyAlligatorException("The Form Tag is not valid according to the grammar specification. Please check that there ONE Form Tag");
		throw (ex);
	}

	return true;
}

/**
	Return false if any of Input tags is malformed 
*/
bool grammarNormalizer::checkInputParameterTags(String^ html){
	// Validating Input Tags
	String^ regExpInput = "(<input)(.*?)/>";
	Regex^ rxInput = gcnew Regex(regExpInput, static_cast<RegexOptions>(RegexOptions::IgnoreCase));
	MatchCollection^ matchesInput = rxInput->Matches(html);
	
	for each (Match^ match in matchesInput){
		int index = match->Index;
		int length = match->Length;
		String^ htmlTag = html->Substring(index,length);
		if (!validateInputTag(htmlTag)){
			return false;
		}
	}
	
	// Validating TextArea Tags
	String^ regExpTextArea = "(<textarea)(.*?)</textarea>";
	Regex^ rxTextArea = gcnew Regex(regExpTextArea, static_cast<RegexOptions>(RegexOptions::IgnoreCase));
	MatchCollection^ matchesTextArea = rxTextArea->Matches(html);
	
	for each (Match^ match in matchesTextArea){
		int index = match->Index;
		int length = match->Length;
		if (!validateTextAreaTag(html->Substring(index,length))){
			return false;
		}
	}

	// Validating Select Tags
	String^ regExpSelect = "(<select)(.*?)</select>";
	Regex^ rxSelect = gcnew Regex(regExpSelect, static_cast<RegexOptions>(RegexOptions::IgnoreCase));
	MatchCollection^ matchesSelect = rxSelect->Matches(html);
	
	for each (Match^ match in matchesSelect){
		int index = match->Index;
		int length = match->Length;
		if (!validateSelectTag(html->Substring(index,length))){
			return false;
		}
	}
	return true;
}
